#include <public/caclient_iface_v1.h>

// ***********************************************************************

// class EDROOMTopContext

// ***********************************************************************



	// CONSTRUCTORES***********************************************

CAClient::EDROOMTopContext::EDROOMTopContext (CAClient &act, TEDROOMBool & EDROOMpVarVresAck, TEDROOMUInt8 & EDROOMpVarVresId, CEDROOMPOOLTEDROOMUInt8 & EDROOMpPoolTEDROOMUInt8 ):

	EDROOMcomponent(act)
	,Msg(EDROOMcomponent.Msg)
	,MsgBack(EDROOMcomponent.MsgBack)
	,EDROOMParameter(EDROOMcomponent.EDROOMParameter)
	,pServReq(EDROOMcomponent.pServReq)
	,ResConfigTimer(EDROOMcomponent.ResConfigTimer)
	,Timer(EDROOMcomponent.Timer)
	, VresAck ( EDROOMpVarVresAck )
	, VresId ( EDROOMpVarVresId )
	, EDROOMPoolTEDROOMUInt8 ( EDROOMpPoolTEDROOMUInt8 )
 {

}

CAClient::EDROOMTopContext::EDROOMTopContext ( EDROOMTopContext &contex ):

	EDROOMcomponent(contex.EDROOMcomponent),
	Msg(contex.Msg),
	MsgBack(contex.MsgBack)
	,EDROOMParameter(contex.EDROOMParameter)
	,pServReq(contex.pServReq)
	,ResConfigTimer(contex.ResConfigTimer)
	,Timer(contex.Timer)
	, VresAck ( contex.VresAck )
	, VresId ( contex.VresId )
	, EDROOMPoolTEDROOMUInt8 ( contex.EDROOMPoolTEDROOMUInt8 )
 {

}

	// EDROOMSearchContextTrans********************************************

bool CAClient::EDROOMTopContext::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 switch(Msg->signal){

		 case ( EDROOMSignalDestroy ): 

			 edroomValidMsg=true;
			 edroomCurrentTrans.distanceToContext = 0 ;
			 edroomCurrentTrans.localId = -1 ;
			 break;

	}

	return(edroomValidMsg);

}

	// Component Methods  ****************************

void	CAClient::EDROOMTopContext::FFreeRes()

{
 
	TEDROOMUInt8 * ap_TEDROOMUInt8 = EDROOMPoolTEDROOMUInt8.AllocData();
	
		// Complete Data 
	
	*ap_TEDROOMUInt8 = VresId;
	
		// send new Msg
	
	pServReq.send(SFreeRes, EDROOMprioNormal, ap_TEDROOMUInt8, &EDROOMPoolTEDROOMUInt8);
	
 
 
 
 
}



void	CAClient::EDROOMTopContext::FProgRequest()

{
 
		// Timing Service 
	 
			//Useful related methods
			 
			//Pr_Time	interval(Pr_Time::millis,int); // Declare time var with an initial value in ms
			//Pr_Time	interval(Pr_Time::micros,int); // Declare time var with an initial value in microseg
	Pr_Time	interval(EDROOMParameter.m_ReqPeriod); // Declare time var with an initial value in seconds
	 
	Timer.InformIn( interval, EDROOMprioNormal );
 
 cout << EDROOMcomponent.EDROOMName << "is sleeping\n";
 
 
}



void	CAClient::EDROOMTopContext::FProgWait()

{
 
		// Timing Service 
	 
			//Useful related methods
			 
			//Pr_Time	interval(Pr_Time::millis,int); // Declare time var with an initial value in ms
			//Pr_Time	interval(Pr_Time::micros,int); // Declare time var with an initial value in microseg
        Pr_Time	interval(EDROOMParameter.m_WaitPeriod); // Declare time var with an initial value in seconds
	 
	Timer.InformIn( interval, EDROOMprioNormal );
 
 cout <<EDROOMcomponent.EDROOMName << "is waiting \n";
 
 
}



void	CAClient::EDROOMTopContext::FProgWork()

{
 
		// Timing Service 
	 
			//Useful related methods
			 
			//Pr_Time	interval(Pr_Time::millis,int); // Declare time var with an initial value in ms
			//Pr_Time	interval(Pr_Time::micros,int); // Declare time var with an initial value in microseg
	Pr_Time	interval(2.0); // Declare time var with an initial value in seconds
	 
	Timer.InformIn( interval, EDROOMprioNormal );
 
 cout << EDROOMcomponent.EDROOMName << "is working\n";
 
 
}



void	CAClient::EDROOMTopContext::FResRequest()

{
 
		// invoke 
	
	MsgBack=pServReq.invoke(SResReq, EDROOMprioNormal);
	
		// Handling MsgBack
	
	if(MsgBack->signal==SResAck){
           VresAck=true;
           VresId=*(TEDROOMUInt8*) (MsgBack->data);
        }
	else
            VresAck=false;
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);
 
 
 
 
 
}



// ***********************************************************************

// class EDROOM_CTX_Working_3

// ***********************************************************************



	// CONSTRUCTORES***********************************************

CAClient::EDROOM_CTX_Working_3::EDROOM_CTX_Working_3( EDROOMTopContext &contex, TEDROOMBool & EDROOMpVarVresConfigOK ):

	EDROOMTopContext(contex)
	, VresConfigOK ( EDROOMpVarVresConfigOK )
{

}

CAClient::EDROOM_CTX_Working_3::EDROOM_CTX_Working_3( EDROOM_CTX_Working_3 &contex ):

	EDROOMTopContext(contex)
	, VresConfigOK ( contex.VresConfigOK )
 {

}

	// EDROOMSearchContextTrans********************************************

bool CAClient::EDROOM_CTX_Working_3::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 switch(Msg->signal){

		 case (EDROOMSignalTimeout): 

				if ( *Msg->GetPInterface() == Timer) {

					 edroomValidMsg=true;
					edroomCurrentTrans.localId = EDROOMTopContext::FreeRes;
					edroomCurrentTrans.distanceToContext = 1 ;
				 }

			 break;

	}

	if (!edroomValidMsg) {

		 edroomValidMsg = EDROOMTopContext::EDROOMSearchContextTrans(edroomCurrentTrans);
		 if (edroomValidMsg) edroomCurrentTrans.distanceToContext++;
	}

	return(edroomValidMsg);

}

	// Component Methods  ****************************

void	CAClient::EDROOM_CTX_Working_3::FProgResConfig()

{
 
		// Timing Service 
	 
			//Useful related methods
			 
	Pr_Time	interval(0.2); // Declare time var with an initial value in seconds
	 
	ResConfigTimer.InformIn( interval, EDROOMprioNormal );
 
 
 
 
}



void	CAClient::EDROOM_CTX_Working_3::FResConfigOK()

{
 
 cout << EDROOMcomponent.EDROOMName << "Res" << (int) VresId << "Config OK\n";
  
 
 
}



void	CAClient::EDROOM_CTX_Working_3::FTryResConfig()

{
 
 VresConfigOK=DriverTryResConfig();
 
 
 
}



	//*****Pools

	//CEDROOMPOOLTEDROOMUInt8

CAClient::EDROOMTopContext::CEDROOMPOOLTEDROOMUInt8::CEDROOMPOOLTEDROOMUInt8(TEDROOMUInt32 elemCount, TEDROOMUInt8* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (TEDROOMUInt8)){;}

TEDROOMUInt8 *	CAClient::EDROOMTopContext::CEDROOMPOOLTEDROOMUInt8::AllocData(){
	return(TEDROOMUInt8*)CEDROOMProtectedMemoryPool::AllocData();
}



// ***********************************************************************

// class EDROOMTopState

// ***********************************************************************



	// CONSTRUCTOR*************************************************

CAClient::EDROOMTopState::EDROOMTopState (CAClient &act, CEDROOMMemory *pEDROOMMemory  ):
	  EDROOMTopContext( act 
		, VresAck
		, VresId
		, EDROOMPoolTEDROOMUInt8 )
	, EDROOMWorking( Working , *this )
	, EDROOMPoolTEDROOMUInt8 ( 10, pEDROOMMemory->poolTEDROOMUInt8, pEDROOMMemory->poolMarkTEDROOMUInt8)
{

}

	// EDROOMBehaviour**********************************************

void CAClient::EDROOMTopState::EDROOMBehaviour(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans = EDROOMIllegada();

	do{

		switch(edroomCurrentTrans.localId){

			case(Init):
				edroomNextState = Idle;
				break;
			case(ReqRes):
				FResRequest();

				EDROOMcomponent.EDROOMTraceStateEntry();

				if( VresAck ){
					edroomCurrentTrans.localId = ReqRes_Ack;
					edroomNextState = Working;
				 } 
				else{
					edroomCurrentTrans.localId = ReqRes_Nack;
					edroomNextState = WaitingRes;
				 } 
				EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
				break;
			case(TryAgain):
				FResRequest();

				EDROOMcomponent.EDROOMTraceStateEntry();

				if( VresAck ){
					edroomCurrentTrans.localId = TryAgain_Ack;
					edroomNextState = Working;
				 } 
				else{
					edroomCurrentTrans.localId = TryAgain_Nack;
					edroomNextState = WaitingRes;
				 } 
				EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
				break;
			case(FreeRes):
				FFreeRes();
				edroomNextState = Idle;
				break;
		}

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(I):
				edroomCurrentTrans=EDROOMIllegada();
				break;

			case(Idle):
				FProgRequest();
				edroomCurrentTrans=EDROOMIdlellegada();
				break;

			case(WaitingRes):
				FProgWait();
				edroomCurrentTrans=EDROOMWaitingResllegada();
				break;

			case(Working):
				FProgWork();
				edroomCurrentTrans=EDROOMWorking.llegada((IdTrans)edroomCurrentTrans.localId);
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

	}while(Msg->signal != EDROOMSignalDestroy);

}



	// Inicio**********************************************

void CAClient::EDROOMTopState::EDROOMInicio(){

EDROOMWorking.EDROOMInicio();
edroomCurrentState=I;

}



//	 ***********************************************************************

//	 llegada SubEstado I

//	 ***********************************************************************



TEDROOMTransId CAClient::EDROOMTopState::EDROOMIllegada(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans.localId = Init;
	edroomCurrentTrans.distanceToContext = 0;
	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, 0);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja Idle

	// ***********************************************************************



TEDROOMTransId CAClient::EDROOMTopState::EDROOMIdlellegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == Timer) {

					edroomCurrentTrans.localId = ReqRes;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja WaitingRes

	// ***********************************************************************



TEDROOMTransId CAClient::EDROOMTopState::EDROOMWaitingResllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == Timer) {

					edroomCurrentTrans.localId = TryAgain;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



// ***********************************************************************

// class EDROOM_SUB_Working_3

// ***********************************************************************



	// CONSTRUCTOR*************************************************

CAClient::EDROOM_SUB_Working_3::EDROOM_SUB_Working_3(EDROOMTopContext::edroomStateId idEst, EDROOMTopContext &contex ):
	  EDROOM_CTX_Working_3( contex , VresConfigOK )
{ idEstado =idEst; }

	// llegada **********************************************

TEDROOMTransId CAClient::EDROOM_SUB_Working_3::llegada(EDROOMTopContext::IdTrans transLlegada){

	TEDROOMTransId edroomCurrentTrans;

	int salirContexto;

	switch (transLlegada){

		case(EDROOMTopContext::ReqRes_Ack):
			edroomCurrentTrans.localId= ToResConfig2;
			edroomNextState = ResConfig;
			break;
		case(EDROOMTopContext::TryAgain_Ack):
			edroomCurrentTrans.localId= ToResConfig;
			edroomNextState = ResConfig;
			break;
		case(EDROOMTopContext::EDROOMMEMORIA):
			edroomCurrentTrans.localId = EDROOMMEMORIA ;
			edroomNextState = edroomCurrentState;
			break;
		default:
			edroomCurrentTrans.localId = EDROOMMEMORIA ;
			edroomNextState = edroomCurrentState;
			break;
	}

	do{

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(ResConfig):
				FProgResConfig();
				edroomCurrentTrans=EDROOMResConfigllegada();
				break;

			case(DoWork):
				edroomCurrentTrans=EDROOMDoWorkllegada();
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

		if (edroomCurrentTrans.distanceToContext == 0){

			switch (edroomCurrentTrans.localId){

				case(TryResConfig):
					FTryResConfig();

					EDROOMcomponent.EDROOMTraceStateEntry();

					if( VresConfigOK ){
						FResConfigOK();
						edroomCurrentTrans.localId = TryResConfig_ResConfigOK;
						edroomNextState = DoWork;
						salirContexto=0;
					 } 
					else{
						edroomCurrentTrans.localId = TryResConfig_ResConfigError;
						edroomNextState = ResConfig;
						salirContexto=0;
					 } 
					EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
					break;
			}

		}else salirContexto=1;

	}while(!salirContexto);

	edroomCurrentTrans.distanceToContext--;

	return(edroomCurrentTrans);

}



	// Inicio**********************************************

void CAClient::EDROOM_SUB_Working_3::EDROOMInicio(){

}



	// ***********************************************************************

	// llegada SubEstado Hoja ResConfig

	// ***********************************************************************



TEDROOMTransId CAClient::EDROOM_SUB_Working_3::EDROOMResConfigllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == ResConfigTimer) {

					edroomCurrentTrans.localId = TryResConfig;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja DoWork

	// ***********************************************************************



TEDROOMTransId CAClient::EDROOM_SUB_Working_3::EDROOMDoWorkllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



